/*******************************************************************************
 * (c) Copyright 2017 lvxi. All Rights Reserved.
 ******************************************************************************/

package edu.jxufe.nb112.common.security.shiro;

import edu.jxufe.nb112.common.code.security.mode.IUserAuth;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by lvxi on 2017/2/9.
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private static final Logger LOG = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class.getName());


    CacheManager cacheManager;

    private  Integer maxRetry=5;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        String account = (String) token.getPrincipal();
        boolean matches = super.doCredentialsMatch(token, info);
        Cache cache =cacheManager.getCache("retry");

        Integer retryCount = getMaxRetry();

        AtomicInteger loginErrorCount = null;
        if(retryCount!=null && retryCount>0){

            Object obj=  cache.get(account);
            Long afterDateL = null;
            if(obj instanceof  AtomicInteger){
                loginErrorCount = (AtomicInteger) obj;
            }else if(obj instanceof Long){
                afterDateL = (Long) obj;
            }
            if(afterDateL==null) {
                if (loginErrorCount == null) {
                    loginErrorCount = new AtomicInteger(0);
                }
                if (loginErrorCount.incrementAndGet() > retryCount) {
                    //10分钟后重试
                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date afterDate = new Date(System.currentTimeMillis() + 60000);
                    cache.put(account, afterDate.getTime());
                    throw new ExcessiveAttemptsException(dateFormat.format(afterDate));
                }
            }else{
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date afterDate = new Date(afterDateL);
                throw new ExcessiveAttemptsException(dateFormat.format(afterDate));
            }
        }

        if(matches){
            if ( info instanceof  UserAuthenticationInfo){
                UserAuthenticationInfo userAuthenticationInfo = (UserAuthenticationInfo) info;
                IUserAuth userAuth = userAuthenticationInfo.getUserAuth();
                if(!userAuth.getEnable()){
                    throw new LockedAccountException();
                } else if(userAuth.getLimitDate()!=null && userAuth.getLimitDate().compareTo(new Timestamp(System.currentTimeMillis()))>0 ){
                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    throw new LockedAccountException(dateFormat.format(userAuth.getLimitDate()));
                }
                cache.remove(account);
            }
        }else if(loginErrorCount!=null) {
            cache.put(account,loginErrorCount);

        }

        return matches;
    }

    public Integer getMaxRetry() {
        return maxRetry;
    }

    public void setMaxRetry(Integer maxRetry) {
        this.maxRetry = maxRetry;
    }

    public CacheManager getCacheManager() {
        return cacheManager;
    }

    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }
}
